package com.huyi.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * java反射
 * 
 * @author shengli.hu
 *
 */
public class ClassReflectDemo {

	public static void main(String[] args) throws Exception {
		
		// 获取Class对象的三种方式
		//	1、forName（String  className）---- 类要指定包路径
		Class<?> clazz = Class.forName("com.huyi.reflect.Student");
		//	2、new Object ——> getClass();
		Class<?>  clazz2 = new Student().getClass();
		//	3、静态的class属性
		Class<?>  clazz3 = Student.class;
		
		// 都一样，用1、clazz举例
		// 获取所有公有构造方法
		System.out.println("**********************所有公有构造方法*********************************");
		Constructor[] conArray = clazz.getConstructors();
		for(Constructor c : conArray){
			System.out.println(c);
		}
		
		System.out.println("************所有的构造方法(包括：私有、受保护、默认、公有)***************");
		conArray = clazz.getDeclaredConstructors();
		for(Constructor c : conArray){
			System.out.println(c);
		}
		
		System.out.println("*****************获取公有、无参的构造方法*******************************");
		Constructor con = clazz.getConstructor(null);
		//1>、因为是无参的构造方法所以类型是一个null,不写也可以：这里需要的是一个参数的类型，切记是类型
		//2>、返回的是描述这个无参构造函数的类对象。
	
		System.out.println("con = " + con);
		//调用构造方法
		Object obj = con.newInstance();
		System.out.println("obj = " + obj);
		Student stu = (Student)obj;
		
		System.out.println("******************获取私有构造方法，并调用*******************************");
		con = clazz.getDeclaredConstructor(char.class);
		System.out.println(con);
		//调用构造方法
		con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
		obj = con.newInstance('男');

		
		System.out.println("******************调用成员方法*******************************");
		Method mShow = clazz.getMethod("show", String.class);
		// 实例化一个对象
		Object obj1 = clazz.getConstructor().newInstance();
		Object result = mShow.invoke(obj1, "20");//需要两个参数，一个是要调用的对象（获取有反射），一个是实参
		System.out.println("返回值：" + result);
	}
}

class Student {
	//---------------构造方法-------------------
		//（默认的构造方法）
		Student(String str){
			System.out.println("(默认)的构造方法 s = " + str);
		}
		
		//无参构造方法
		public Student(){
			System.out.println("调用了公有、无参构造方法执行了。。。");
		}
		
		//有一个参数的构造方法
		public Student(char name){
			System.out.println("姓名：" + name);
		}
		
		//有多个参数的构造方法
		public Student(String name ,int age){
			System.out.println("姓名："+name+"年龄："+ age);//这的执行效率有问题，以后解决。
		}
		
		//受保护的构造方法
		protected Student(boolean n){
			System.out.println("受保护的构造方法 n = " + n);
		}
		
		//私有构造方法
		private Student(int age){
			System.out.println("私有的构造方法   年龄："+ age);
		}

		/**
		 * 成员方法
		 * 
		 * @param s
		 */
		public String show(String s){
			System.out.println("调用了：公有的，String参数的show(): s = " + s);
			return "show(): s = " + s;
		}
}
